{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "60ea77f8",
   "metadata": {},
   "source": [
    "------\n",
    "* 学习人：纪秋霞\n",
    "* 时间：2021-12-02\n",
    "* week14\n",
    "* 学习线上资源：\n",
    "\n",
    "> 1.[python官方文档](https://python.org/doc)\n",
    "\n",
    "> 2.[老师博客](https://www.cnblogs.com/xuzhichao/p/11570285.html)\n",
    "------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "258689da",
   "metadata": {},
   "source": [
    "# 函数\n",
    "\n",
    "## 1. [函数的定义](https://docs.python.org/3/tutorial/controlflow.html#defining-functions)\n",
    "> 1. 数学：     f(x) = ax + b\n",
    "> 2. python:  def fib(x)：\n",
    "> 3. 编程思维 vs 数学思维\n",
    ">> 1. 函数可被定义名称，定义的关键字： <font style=\"color:red\">**def**</font>\n",
    ">> 2. 数学思维是写在同一行（即 定义函数 和 运算公式），面向对象编程中，定义函数为单独一行，函数写多行\n",
    ">> 3. 数学一般没有注释，而编程中一般需要对函数进行注释描述（课本P151）\n",
    ">> 4. 数学中：ax+b 是运算公式，而编程中，将其称为**函数体**，函数体要有一定的**缩进**（比def往右缩进）\n",
    ">> 5. 数学函数执行，将参数代入公式  编程中函数执行，将参数代入函数体\n",
    "\n",
    "## 2. [关于函数的更多定义](https://docs.python.org/3/tutorial/controlflow.html#more-on-defining-functions)\n",
    "\n",
    "> 1. 函数的参数\n",
    ">> 1. 形式参数\n",
    ">> 2. 实际参数\n",
    ">> 3. 位置参数\n",
    ">> 4. 关键字参数\n",
    ">> 5. 默认参数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2316c2e",
   "metadata": {},
   "source": [
    "> 1. 定义函数\n",
    "```\n",
    "def:定义函数的关键字\n",
    "flb：函数名\n",
    "(n)：定义函数的参数\n",
    "\"\"\"\"\"\"：文档描述: 与使用者进行交互的唯一途径\n",
    "代码块：\n",
    "     a, b = 0, 1\n",
    "     while a < n:\n",
    "        print(a, end=' ')\n",
    "         a, b = b, a+b\n",
    "     print()\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "20c64401",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 斐波那契数列：0 1 1 2 3 5 8 13 21 24...\n",
    "# python官网案例\n",
    "\n",
    "# 定义函数\n",
    "def fib(x):\n",
    "    # 注释\n",
    "    \"\"\"Print a Fibonacci series up to x.\"\"\"\n",
    "    # 列出指定x以内的斐波那契数列\n",
    "    a, b = 0, 1\n",
    "    while a < x:\n",
    "        print(a, end=' ')\n",
    "        a, b = b, a+b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b3a51a62",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 1 2 3 5 8 13 21 34 55 89 "
     ]
    }
   ],
   "source": [
    "fib(100)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "30a02f98",
   "metadata": {},
   "outputs": [],
   "source": [
    "## 实践: 写一个函数，打印： “你好，xxx同学”\n",
    "def hello(name):\n",
    "    \"\"\"问好\"\"\"\n",
    "    print(\"你好，%s同学\"%(name))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "acd29117",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好，Lihua同学\n"
     ]
    }
   ],
   "source": [
    "hello(\"Lihua\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2de75c19",
   "metadata": {},
   "source": [
    "> 2. 调用函数/使用函数\n",
    ">> 1. 函数名(参数)\n",
    ">> 2. 参数可以不存在"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "394807a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 参数可以不存在\n",
    "def hello():\n",
    "    \"\"\"问好\"\"\"\n",
    "    print(\"hello world\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "c8a34261",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello world\n"
     ]
    }
   ],
   "source": [
    "hello()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "bd242e02",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 回顾与思考\n",
    "import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "70b84193",
   "metadata": {},
   "outputs": [],
   "source": [
    "# sleep() 需要给定一个时间（int）参数\n",
    "time.sleep(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "f9e216c1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "time.struct_time(tm_year=2021, tm_mon=12, tm_mday=2, tm_hour=10, tm_min=46, tm_sec=55, tm_wday=3, tm_yday=336, tm_isdst=0)"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# localtime() 不需要给定参数\n",
    "time.localtime()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "e05dc23e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on built-in function localtime in module time:\n",
      "\n",
      "localtime(...)\n",
      "    localtime([seconds]) -> (tm_year,tm_mon,tm_mday,tm_hour,tm_min,\n",
      "                              tm_sec,tm_wday,tm_yday,tm_isdst)\n",
      "    \n",
      "    Convert seconds since the Epoch to a time tuple expressing local time.\n",
      "    When 'seconds' is not passed in, convert the current time instead.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(time.localtime)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03c10aa1",
   "metadata": {},
   "source": [
    "> 3. 函数的优势\n",
    ">> 1. 可以重复使用相同的功能，避免重复造轮子\n",
    ">> 2. 使用者可以不了解函数本身，只需要清除如何使用即可\n",
    ">> 3. 使用/调用方便，只需要清楚传递的函数名及参数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93daa13f",
   "metadata": {},
   "source": [
    "# 3. 函数的参数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf6007d5",
   "metadata": {},
   "source": [
    "> 1. 形式参数(形参)\n",
    ">> 1. 在**函数**的时候定义的参数\n",
    ">> 2. 形参不占用内存\n",
    "> 2. 实际参数(实参)\n",
    ">> 1. 在**调用**函数的时候传递的参数\n",
    ">> 2. 调用函数时，形参分配空间，传递实参，执行函数内容"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "646705d6",
   "metadata": {},
   "source": [
    "```\n",
    "# 课本案例\n",
    "def search4vowels(word):\n",
    "    \"\"\"\n",
    "    显示文本中出现的元音字母有哪些\n",
    "    \n",
    "    word是文本信息，请输入正确的文本给word\n",
    "    \"\"\"\n",
    "    vowels = set(\"aeiou\")\n",
    "    word = set(word)\n",
    "    print(vowels & word)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "697e6526",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function search4vowels in module __main__:\n",
      "\n",
      "search4vowels(word)\n",
      "    显示文本中出现的元音字母有哪些\n",
      "    \n",
      "    word是文本信息，请输入正确的文本给word\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(search4vowels)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "ec720922",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 课本案例\n",
    "def search4vowels(word):\n",
    "    \"\"\"显示文本中出现的元音字母有哪些\"\"\"\n",
    "    vowels = set(\"aeiou\")\n",
    "    word = set(word)\n",
    "    print(vowels & word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "0cf8c055",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'a', 'o', 'u', 'e', 'i'}\n"
     ]
    }
   ],
   "source": [
    "search4vowels(\"ghjgjyiioqualdkuoe\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00b5d468",
   "metadata": {},
   "source": [
    "> 1. 形参：word\n",
    ">> 形式参数，不是实际存在的，是虚拟变量。在定义函数和函数体的时候使用形参，目的是在函数调用时接收实参\n",
    "> 2. 实参：ghjgjyiioqualdkuoe\n",
    ">> 实际参数，调用函数时传递给函数的参数，可以是常量、变量，表达式，函数，传给形参\n",
    "> 3. 区别：形参是虚拟的，不占用空间，形参变量只有在被调用时才分配内存单元，实参是一个变量，占用内存空间，数据传递单向，实参传给形参，不能倒过来。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2088028b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 期末 外部端的小应用\n",
    "# 有事例代码\n",
    "# 课本 第五章第六章\n",
    "# 17周公布 18-19周做，gitee交"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6cec5f9f",
   "metadata": {},
   "source": [
    "* 在多个参数的情况下\n",
    "\n",
    "> 1. 位置参数\n",
    ">> 1. 在形参的定义中，有一定的先后顺序\n",
    ">> 2. 在调用函数时，要考虑形参的先后顺序\n",
    ">> 3. 调用函数时，不仅要考虑参数的位置，还需考虑形参的个数\n",
    "> 2. 关键字参数\n",
    ">> 1. 在调用函数时，可以不考虑形参的位置\n",
    ">> 2. 关键字参数是不可以写在位置参数前面的\n",
    "> 3. 默认参数\n",
    ">> 1. 调用函数时，可以省略传递的参数信息\n",
    ">> 2. 调用函数时,如果给默认参数赋值,会替换默认参数的结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "c1a2a3f4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. 位置参数\n",
    "def describe_pet(pet_name,animal_type):\n",
    "    \"\"\"显示宠物信息\"\"\"\n",
    "    print(\"\\nI have a \" + animal_type + \".\")\n",
    "    print(\"My \" + animal_type + \"'s name is \"+pet_name.title() + \".\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "28cda70a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a dog.\n",
      "My dog's name is 豆豆.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"豆豆\",\"dog\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "8edb057d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a cat.\n",
      "My cat's name is 微积分.\n"
     ]
    }
   ],
   "source": [
    "# 2. 关键字参数\n",
    "describe_pet(animal_type= \"cat\",pet_name=\"微积分\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "aac3bbbd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3. 默认参数\n",
    "def describe_pet(pet_name,animal_type=\"dog\"):\n",
    "    \"\"\"显示宠物信息\"\"\"\n",
    "    print(\"\\nI have a \" + animal_type + \".\")\n",
    "    print(\"My \" + animal_type + \"'s name is \"+pet_name.title() + \".\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "9e4e34ba",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a dog.\n",
      "My dog's name is 豆豆.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"豆豆\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "9e9811f5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a cat.\n",
      "My cat's name is 豆豆.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"豆豆\",\"cat\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52064482",
   "metadata": {},
   "source": [
    "* 参数的注意事项实践\n",
    "\n",
    "> 1. 位置参数和关键字参数同时使用（调用函数时）\n",
    ">> 1. positional argument follows keyword argument(关键字参数<font style=\"color:red\">均</font>应该放在位置参数之后)\n",
    ">> 2. 只要满足1的条件，剩余的（多个）关键字参数不考虑先后顺序\n",
    "> 2. 非默认参数和默认参数同时使用（定义函数时）\n",
    ">> 1. non-default argument follows default argument（默认参数<font style=\"color:red\">均</font>应该放在非默认参数之后）\n",
    ">> 2. 只要满足1的条件，剩余的（多个）默认参数不考虑先后顺序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "54ccbc2d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 测试1\n",
    "def test(x,y,z):\n",
    "    \"\"\"打印x,y,z的结果\"\"\"\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "920f11d7",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "positional argument follows keyword argument (<ipython-input-63-0d3bd7e3ec53>, line 2)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-63-0d3bd7e3ec53>\"\u001b[1;36m, line \u001b[1;32m2\u001b[0m\n\u001b[1;33m    test(5,y=3,2)\u001b[0m\n\u001b[1;37m               ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m positional argument follows keyword argument\n"
     ]
    }
   ],
   "source": [
    "# 实践1\n",
    "test(5,y=3,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "41ecf6d7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "3\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "# 实践2\n",
    "test(5,3,z=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "35112f0f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "3\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "# 实践3\n",
    "test(5,z=2,y=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "45478dd2",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "non-default argument follows default argument (<ipython-input-66-0de206ab27d0>, line 2)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-66-0de206ab27d0>\"\u001b[1;36m, line \u001b[1;32m2\u001b[0m\n\u001b[1;33m    def test(x,y=1,z):\u001b[0m\n\u001b[1;37m             ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m non-default argument follows default argument\n"
     ]
    }
   ],
   "source": [
    "# 测试2\n",
    "def test(x,y=1,z):\n",
    "    \"\"\"打印x,y,z的结果\"\"\"\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "4aff4758",
   "metadata": {},
   "outputs": [],
   "source": [
    "def test(x,z,y=1):\n",
    "    \"\"\"打印x,y,z的结果\"\"\"\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9ec294b2",
   "metadata": {},
   "source": [
    "### 课后练习"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "4b2e98b4",
   "metadata": {},
   "outputs": [],
   "source": [
    "def search4vowels():\n",
    "    vowels = set('aeiou')\n",
    "    word = input(\"Provide a word to search for vowels:\")\n",
    "    found = vowels.intersection(set(word))\n",
    "    for vowel in found:\n",
    "        print(vowel)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "5bcca3d3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Provide a word to search for vowels:hello world\n",
      "o\n",
      "e\n"
     ]
    }
   ],
   "source": [
    "search4vowels()\n",
    "# search4vowels() #可以重复多次调用"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
